#include "sessionlist.h"
#include "debug.h"

//----------------------------------------------------------------------------------------------------------------------------------
/// 滚动区域的类
//----------------------------------------------------------------------------------------------------------------------------------

// 构造函数
SessionList::SessionList(QWidget* parent)
    : QScrollArea {parent}  //调用基类的构造函数，如果不指定的话，会调用无参默认构造函数
{
    // 设置这个属性才可以开启滚动效果
    this->setWidgetResizable(true);
    // 设置滚动条相关样式
    // 垂直方向
    this->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 0px; }");
    // 水平方向
    this->horizontalScrollBar()->setStyleSheet("QScrollBar:horizontal { height: 0px; }");
    // 取消边框的线
    this->setStyleSheet("QWidget { border: none; }");

    // 设置滚动区域
    container = new QWidget();
    container->setFixedWidth(230);
    // 告诉滚动区，要和哪一个QWidget进行配合实现滚动，也就是检测哪一个QWidget的高度
    this->setWidget(container);

    // 给QWidget添加布局管理器
    QVBoxLayout* layout = new QVBoxLayout();
    container->setLayout(layout);
    // 设置内部元素距离父窗口的距离 和 内部元素之间的距离
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    // 设置靠上对齐
    layout->setAlignment(Qt::AlignTop);

#if TEST_UI
    QIcon icon(":/image/people.png");
    for(int i = 0; i < 30; i++)
    {
        this->addItem(ItemType::ApplyItemType, QString::number(i), icon, "哈哈" + QString::number(i), "这是最后一条消息" + QString::number(i));
    }
#endif
}

// 清空列表区域
void SessionList::clear()
{
    // 取出layout--只能拿到一个父类指针，无法直接体现出来是哪一种布局管理器
    QLayout* layout = container->layout();
    // 遍历布局管理器中的所以元素，并依次删除
    // 不可以这样删除，因为在删除的过程当中，layout->count的值就会一直变小了，i还一直增大，那么就会出现问题了。和迭代器失效问题类似
    // for(int i = 0; i < layout->count(); i++) { layout->takeAt(i); }
    // 可以从后向前删除，从后向前删除的时候不要使用size_t类型，如今开发的一般不会使用size_t类型，这个类型是远古时期为了节省减少内存消耗设计的。
    for(int i = layout->count() - 1; i >= 0; i--)
    {
        QLayoutItem* item = layout->takeAt(i);
        // 上面只是移除了，还需要释放内存
        if(item->widget())
        {
            delete item->widget();
        }
    }
}

// // 添加一个会话
// void SessionList::addItem(const QIcon &avator, const QString &nickName, const QString &text)
// {
//     // 创建一个会话对象
//     SessionFriendApplyItem* item = new SessionFriendApplyItem(this, avator, nickName, text);
//     // 添加到布局管理器中--先去出来container的layout之后，添加到layout当中
//     container->layout()->addWidget(item);
// }

// 根据不同类型，生成不同的元素
void SessionList::addItem(const ItemType itemType, const QString& id, const QIcon &avator, const QString &nickName, const QString &text)
{
    SessionFriendApplyItem* item = nullptr;
    if(itemType == ItemType::SessionItemType)
    {
        item = new SessionItem(this, id, avator, nickName, text);
    }
    else if(itemType == ItemType::FriemdItemType)
    {
        item = new FriendItem(this, id, avator, nickName, text);
    }
    else if(itemType == ItemType::ApplyItemType)
    {
        item = new ApplyItem(this, id, avator, nickName);
    }
    else
    {
        LOG() << "未知的ItemType: " << itemType;
        return;
    }
    // 放入到滚动区域中
    container->layout()->addWidget(item);
}


// 选中某个指定的Item元素
void SessionList::clickItem(int index)
{
    // 下标是否在合法范围之内
    if(index < 0 || index >= container->layout()->count())
    {
        // 宏的使用不受命名空间的影响
        LOG() << "点击的元素的下标超出了合法的范围: " << index;
        return;
    }
    // 获取布局管理器元素
    QLayoutItem* layoutItem = container->layout()->itemAt(index);
    if(layoutItem == nullptr || layoutItem->widget() == nullptr)
    {
        LOG() << "指定的元素并不存在: " << index;
        return;
    }

    // 强转
    SessionFriendApplyItem* item = dynamic_cast<SessionFriendApplyItem*>(layoutItem->widget());
    // 选中
    item->select();
}

//----------------------------------------------------------------------------------------------------------------------------------
/// 滚动区域中的元素的类
//----------------------------------------------------------------------------------------------------------------------------------

// 构造函数
SessionFriendApplyItem::SessionFriendApplyItem(QWidget *owner, const QIcon &avator, const QString &nickName, const QString &text)
    :owner(owner)
{
    // 设置样式
    this->setFixedHeight(70);
    // 该样式设置没有生效，因为SessionItem并非是一个QWidget类，而是继承自QWidget，而我们使用的qss选择器选择的是QWidget
    // Qt中，如果给QWidget的子类，通过QSS设置背景色，则默认情况下是不生效的，要想生效的话，需要根据官方文档中写一段特殊代码才可以
    this->setStyleSheet("QWidget { background-color: rgb(231, 231, 231); }");

    // 网格布局管理器
    QGridLayout* layout = new QGridLayout();
    this->setLayout(layout);
    // 设置距离
    layout->setContentsMargins(10, 0, 0, 0);
    // 设置元素之间的水平和竖直方向的间距
    layout->setHorizontalSpacing(10);
    layout->setVerticalSpacing(0);

    // 创建头像
    QPushButton* avatorButton = new QPushButton();
    // 设置样式
    avatorButton->setFixedSize(50, 50);
    avatorButton->setIconSize(QSize(50, 50));
    avatorButton->setIcon(avator);
    avatorButton->setStyleSheet("QPushBUtton { border: none; }");
    // 设置大小变动策略，宽度和高度都为固定长度，不随着窗口的尺寸变化而改变。和他对应的是Expanding，尽可能的伸展把父元素填满。perferred由系统自己决定
    avatorButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // 创建名字
    QLabel* nickNameLabel = new QLabel();
    nickNameLabel->setText(nickName);
    nickNameLabel->setStyleSheet("QLabel { font-size: 18px; font-weight: 600; }");
    nickNameLabel->setFixedHeight(35);
    nickNameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    // 最后一条消息or个性签名
    messageLabel = new QLabel();
    messageLabel->setText(text);
    messageLabel->setFixedHeight(35);
    messageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    // 添加到布局管理器当中
    layout->addWidget(avatorButton, 0, 0, 2, 2);
    layout->addWidget(nickNameLabel, 0, 2, 1, 8);
    layout->addWidget(messageLabel, 1, 2, 1, 8);

}

// 确保QWidget子类设置的样式生效
void SessionFriendApplyItem::paintEvent(QPaintEvent *event)
{
    (void)event;
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

// 选中某一个元素
void SessionFriendApplyItem::select()
{
    // 还原其他元素的背景色
    // 先找到父元素，然后取出所有子元素
    const QObjectList childrens = this->parentWidget()->children();
    for(QObject* child : childrens)
    {
        if(!child->isWidgetType())
        {
            continue;
        }
        // 父子类强制转换
        SessionFriendApplyItem* item = dynamic_cast<SessionFriendApplyItem*>(child);
        if(item->isSelected == true)
        {
            // 设置为非选中状态
            item->isSelected = false;
            // 改变颜色
            item->setStyleSheet("QWidget { background-color: rgb(231, 231, 231); }");
        }
    }

    // 设置当前Item的背景色加深
    this->isSelected = true;
    this->setStyleSheet("QWidget { background-color: rgb(210, 210, 210; )}");

    // 调用
    this->active();
}

// 鼠标点击事件
void SessionFriendApplyItem::mousePressEvent(QMouseEvent *event)
{
    // 这里无论是哪个键被点击都会触发，所以要靠event来进行区分--先不做处理
    (void)event;
    select();
}

// 鼠标进入区域的变化
void SessionFriendApplyItem::enterEvent(QEnterEvent *event)
{
    (void)event;
    // 如果是选中状态的话就什么也不做，也就是说，被选中的元素，不受到鼠标进入和移出的影响。
    if(this->isSelected == true)
        return;

    this->setStyleSheet("QWidget { background-color: rgb(215, 215, 215; )}");
}
// 鼠标移出区域的变化
void SessionFriendApplyItem::leaveEvent(QEvent *event)
{
    (void)event;
    // 如果是选中状态的话就什么也不做
    if(this->isSelected == true)
        return;
    this->setStyleSheet("QWidget { background-color: rgb(231, 231, 231; )}");
}

//----------------------------------------------------------------------------------------------------------------------------------
/// 会话元素类
//----------------------------------------------------------------------------------------------------------------------------------

SessionItem::SessionItem(QWidget *owner, const QString& chatSessionId, const QIcon &avator, const QString &nickName, const QString &lastMessage)
    : SessionFriendApplyItem(owner, avator, nickName, lastMessage)   // 先构造父类的部分
    , chatSessionId(chatSessionId)
{

}

// 重写Item被点击之后的逻辑
void SessionItem::active()
{

}

//----------------------------------------------------------------------------------------------------------------------------------
/// 好友元素类
//----------------------------------------------------------------------------------------------------------------------------------

FriendItem::FriendItem(QWidget *owner, const QString &userId, const QIcon &avator, const QString &nickName, const QString &description)
    : SessionFriendApplyItem(owner, avator, nickName, description)
    , userId(userId)
{

}

// 重写Item被点击之后的逻辑
void FriendItem::active()
{

}


//----------------------------------------------------------------------------------------------------------------------------------
/// 好友申请元素类
//----------------------------------------------------------------------------------------------------------------------------------

ApplyItem::ApplyItem(QWidget *owner, const QString &userId, const QIcon &avator, const QString &nickName)
    : SessionFriendApplyItem(owner, avator, nickName, "")
    , userId(userId)
{
    // 取出父类的布局管理器
    QGridLayout* layout = dynamic_cast<QGridLayout*>(this->layout());
    layout->removeWidget(messageLabel);
    // 释放内存
    delete messageLabel;

    // 添加两个按钮--同意和拒绝
    QPushButton* acceptButton = new QPushButton();
    acceptButton->setText("同意");
    QPushButton* rejectButton = new QPushButton();
    rejectButton->setText("拒绝");

    // 添加到布局管理器当中
    layout->addWidget(acceptButton, 1, 2, 1, 2);
    layout->addWidget(rejectButton, 1, 4, 1, 2);
}

// 重写Item被点击之后的逻辑
void ApplyItem::active()
{

}

